package ast.expr

import ast.SqlNode
import ast.order.SqlOrderBy
import ast.statement.select.SqlSelectQuery
import java.math.BigDecimal
import java.text.SimpleDateFormat
import java.util.*

sealed class SqlExpr : SqlNode

data class SqlBinaryExpr(val left: SqlExpr, val operator: SqlBinaryOperator, val right: SqlExpr) : SqlExpr()

data class SqlIdentifierExpr(val name: String) : SqlExpr()

data class SqlPropertyExpr(val owner: String, val name: String) : SqlExpr()

data class SqlNullExpr(val name: String? = null) : SqlExpr()

data class SqlAllColumnExpr(val owner: String? = null) : SqlExpr()

data class SqlNumberExpr(val number: Number) : SqlExpr()

data class SqlDecimalExpr(val number: BigDecimal) : SqlExpr()

data class SqlDataExpr(val date: Date) : SqlExpr() {
    override fun toString(): String {
        val format = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
        return "'${format.format(date)}'"
    }
}

data class SqlCharExpr(val text: String) : SqlExpr() {
    override fun toString(): String {
        return "'${text.replace("'", "''")}'"
    }
}

data class SqlBooleanExpr(val boolean: Boolean) : SqlExpr()

data class SqlListExpr<T : SqlExpr>(val items: List<T> = listOf()) : SqlExpr()

data class SqlAggFunctionExpr(
    val name: String,
    val args: MutableList<SqlExpr> = mutableListOf(),
    val distinct: Boolean = false,
    val attributes: MutableMap<String, SqlExpr> = mutableMapOf(),
    val orderBy: MutableList<SqlOrderBy> = mutableListOf()
) : SqlExpr()

data class SqlExprFunctionExpr(val name: String, var args: MutableList<SqlExpr> = mutableListOf()) : SqlExpr()

data class SqlCastExpr(val expr: SqlExpr, val type: String) : SqlExpr()

data class SqlSelectQueryExpr(val query: SqlSelectQuery) : SqlExpr()

data class SqlInExpr(val expr: SqlExpr, val inExpr: SqlExpr, val isNot: Boolean = false) : SqlExpr()

data class SqlBetweenExpr<T : SqlExpr>(val expr: SqlExpr, val start: T, val end: T, val isNot: Boolean = false) :
    SqlExpr()

data class SqlOverExpr(
    val aggFun: SqlAggFunctionExpr,
    val partitionBy: MutableList<SqlExpr> = mutableListOf(),
    val orderBy: MutableList<SqlOrderBy> = mutableListOf()
) : SqlExpr()

data class SqlCaseExpr(val caseList: MutableList<SqlCase> = mutableListOf(), val default: SqlExpr) : SqlExpr()

data class SqlSubQueryPredicateExpr(val select: SqlSelectQueryExpr, val predicate: SqlSubQueryPredicate) : SqlExpr()